main.c
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_hal.h"
#include "cmsis_os.h"
#include "adc.h"
#include "can.h"
#include "dma.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* USER CODE BEGIN Includes */
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "semphr.h"
#include "My_types.h"
#include "PIN_functions.h"
#include "MATH_functions.h"
#include "MTRX_functions.h"
#include "SPI_functions.h"
#include "FLASH_functions.h"
#include "ETHCAT_functions.h"
#include "CANopen.h"
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
xQueueHandle PWM_Val_queue;
xQueueHandle Temp_queue;
xQueueHandle Fault_queue;
xQueueHandle SKZ_queue;
xQueueHandle Lin_In_queue;
xQueueHandle Dig_In_queue;
xQueueHandle Dig_Out_queue;
xQueueHandle UART_PWM_queue;
xQueueHandle Temp2_queue;
xQueueHandle SKZ2_queue;
xSemaphoreHandle Semaphore_PWM; // Semaphore for synchronization of measurements and normal PWM
extern volatile uint16_t tim_9_pw_rate_chan1; // PWM rate of program timer PWM1
extern volatile uint16_t tim_9_pw_rate_chan2; // PWM rate of program timer PWM2
extern volatile uint16_t tim_9_period; // Period of program timer
extern Work_state_t Measure_1, Measure_2; // State of channels PWM1 and PWM2 (program timer) - normal work or measurement
volatile uint16_t counter = 0; // Counter for program timer
volatile uint8_t mode = 0; // Direction of program counter counting (0 = UP, 1 = DOWN)
UART_param_str xUART; // Structure for UART work
CAN_flag_str xCAN; // Structure with flags to proceed CAN interrupts
volatile uint16_t Vref_VAL = 0; // ADC reference voltage (readed every current measurement cycle)
TaskHandle_t PWM_task_handle; // "Pointer" to PWM_Set_task
TaskHandle_t renew_PWM_handle; // "Pointer" to Receive_PWM_PDO_task
CAN_TxHeaderTypeDef txHeader_TEMP; // Settings structure for CAN temperature (and dig in) transmit
CAN_TxHeaderTypeDef txHeader_CURR; // Settings structure for CAN current transmit
CAN_TxHeaderTypeDef txHeader_LININ; // Settings structure for CAN linear inputs transmit
CAN_TxHeaderTypeDef txHeader_SDO;
CAN_RxHeaderTypeDef recHeader; // Settings structure for CAN PWM receive
CAN_RxHeaderTypeDef recHeader_SDO;
uint8_t recData_raw[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t recDataPWM[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t recDataSDO[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t Flash_flag = 0;
//uint8_t recData_raw[8] = {0, 0, 0, 0, 0, 0, 0, 0};
Settings_str Flash_SETTINGS;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void MX_FREERTOS_Init(void);
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
static void Curr_sens_task (void* pvParameters);
static void FLASH_operations (void* pvParameters);
static void Temp_sens_task (void* pvParameters);
static void Lin_IN_task (void* pvParameters);
static void DIG_IN_task (void* pvParameters);
static void DIG_OUT_task (void* pvParameters);
static void UART_Debug_task (void* pvParameters);
static void ETHCAT_task (void* pvParameters);
static void PWM_Set_task (void* pvParameters);
static void Temp_SEND_CAN_task (void* pvParameters);
static void Receive_PWM_CAN_task (void* pvParameters);
static void Curr_SEND_CAN_task (void* pvParameters);
static void LinIN_SEND_CAN_task (void* pvParameters);
static void Receive_SDO_CAN_task (void* pvParameters);
void CO_TIMER_ISR(void);
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
*
* @retval None
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_ADC2_Init();
MX_ADC3_Init();
MX_SPI1_Init();
MX_SPI3_Init();
MX_TIM1_Init();
MX_TIM3_Init();
MX_TIM4_Init();
MX_TIM5_Init();
MX_TIM8_Init();
MX_USART3_UART_Init();
MX_TIM2_Init();
MX_SPI2_Init();
MX_TIM9_Init();
MX_CAN2_Init();
/* USER CODE BEGIN 2 */
All_timers_start(); // !!!1 let the party begin
Lock_PINs(); // To prevent pins unexpected usage
HAL_UART_Receive_IT(&huart3, xUART.chan_numb, 1);
vTraceEnable(TRC_START);
vSemaphoreCreateBinary(Semaphore_PWM);
/******** Queues Creation ********/
PWM_Val_queue = xQueueCreate(2, sizeof(uint16_t)*CHAN_QUANTITY); // Receive_PWM_PDO_task (or UART_Debug_task) -> PWM_Set_task
if (PWM_Val_queue == NULL)
{while (1);}
Temp_queue = xQueueCreate(1, sizeof(uint32_t)*CHAN_QUANTITY); // Temp_sens_task -> UART_Debug_task
if (Temp_queue == NULL)
{while (1);}
SKZ_queue = xQueueCreate(1, sizeof(float)*CHAN_QUANTITY); // Curr_sens_task -> UART_Debug_task
if (SKZ_queue == NULL)
{while (1);}
Lin_In_queue = xQueueCreate(1, sizeof(uint16_t)*3); // Lin_IN_task -> Send_OUTSIDE (??)
if (Lin_In_queue == NULL)
{while (1);}
Dig_In_queue = xQueueCreate(1, sizeof(uint8_t));// Dig_IN_task -> Temp_SEND_CAN_task
if (Dig_In_queue == NULL)
{while (1);}
Dig_Out_queue = xQueueCreate(1, sizeof(uint8_t));// Receive_PWM_PDO_task -> Dig_OUT_task
if (Dig_Out_queue == NULL)
{while (1);}
Fault_queue = xQueueCreate(1, sizeof(uint8_t) * CHAN_QUANTITY); // Temp_sens_task -> UART_Debug_task
if (Fault_queue == NULL)
{while (1);}
UART_PWM_queue = xQueueCreate(1, sizeof(uint16_t) * CHAN_QUANTITY); // UART_Debug_task -> PWM_Set_task
if (UART_PWM_queue == NULL)
{while (1);}
Temp2_queue = xQueueCreate(1, sizeof(uint16_t) * CHAN_QUANTITY); // Temp_sens_task -> Temp_SEND_CAN_task
if (Temp2_queue == NULL)
{while (1);}
SKZ2_queue = xQueueCreate(1, sizeof(uint16_t) * CHAN_QUANTITY); // Curr_sens_task -> Curr_SEND_CAN_task
if (SKZ2_queue == NULL)
{while (1);}
/******** Tasks Creation ********/
if (xTaskCreate(Curr_sens_task, (char*) "Curr Sens Poll", configMINIMAL_STACK_SIZE * 30, NULL, 2, NULL) == pdFALSE)
{while (1);}
if (xTaskCreate(PWM_Set_task, (char*) "Setting PWM rate", configMINIMAL_STACK_SIZE * 3, NULL, 2, &PWM_task_handle) == pdFALSE)
{while (1);}
if (xTaskCreate(FLASH_operations, (char*) "Change settings", configMINIMAL_STACK_SIZE*20, NULL, 3, NULL) == pdFALSE)
{while (1);}
if (xTaskCreate(Temp_sens_task, (char*) "Temp Sens Poll", configMINIMAL_STACK_SIZE*10, NULL, 1, NULL) == pdFALSE)
{while (1);}
if (xTaskCreate(Lin_IN_task, (char*) "Lin In task", configMINIMAL_STACK_SIZE*2, NULL, 1, NULL) == pdFALSE)
{while (1);}
if (xTaskCreate(DIG_IN_task, (char*) "Dig In Task", configMINIMAL_STACK_SIZE*4, NULL, 1, NULL) == pdFALSE)
{while (1);}
if (xTaskCreate(DIG_OUT_task, (char*) "Dig Out Task", configMINIMAL_STACK_SIZE*4, NULL, 1, NULL) == pdFALSE)
{while (1);}
if (xTaskCreate(UART_Debug_task, (char*) "UART debug", configMINIMAL_STACK_SIZE*10, NULL, 1, NULL) == pdFALSE)
{while (1);}
if (xTaskCreate(ETHCAT_task, (char*) "EtherCAT", configMINIMAL_STACK_SIZE*60, NULL, 1, NULL) == pdFALSE)
{while (1);}
if (xTaskCreate(Temp_SEND_CAN_task, (char*) "Send temperature", configMINIMAL_STACK_SIZE*10, NULL, 1, NULL) == pdFALSE)
{while (1);}
if (xTaskCreate(Receive_PWM_CAN_task, (char*) "Receive new PWM", configMINIMAL_STACK_SIZE*5, NULL, 1, &renew_PWM_handle)== pdFALSE)
{while (1);}
if (xTaskCreate(Curr_SEND_CAN_task, (char*) "Send current", configMINIMAL_STACK_SIZE*5, NULL, 1, &renew_PWM_handle)== pdFALSE)
{while (1);}
if (xTaskCreate(LinIN_SEND_CAN_task, (char*) "Send lin in states", configMINIMAL_STACK_SIZE*5, NULL, 1, &renew_PWM_handle)== pdFALSE)
{while (1);}
if (xTaskCreate(Receive_SDO_CAN_task, (char*) "Rec of SDO data", configMINIMAL_STACK_SIZE*5, NULL, 1, &renew_PWM_handle)== pdFALSE)
{while (1);}
/* USER CODE END 2 */
/* Call init function for freertos objects (in freertos.c) */
MX_FREERTOS_Init();
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
/**Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 6;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure the Systick interrupt time
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 15, 0);
}
/* USER CODE BEGIN 4 */
/*************** SENSORS POLLING TASKS **************/
static void Curr_sens_task (void* pvParameters)
{
TickType_t Prew_wake;
heat_el_t h_el_was_ON[9] = // list of elements that was ON at current cycle of measurements
{ HEL_NO, HEL_NO, HEL_NO, HEL_NO, HEL_NO,
HEL_NO, HEL_NO, HEL_NO, HEL_NO };
SW_state_t resol_of_meas[CHAN_QUANTITY]; // states of switches for current resolution
for(uint8_t i = 0; i < CHAN_QUANTITY; i++)
resol_of_meas[i] = LOW;
// LOW = rough measurement of BIG current
uint16_t ADC1_raw[CUR_RAW_ARR_LENGTH*NUMB_CHAN_PER_ADC1] = {0}; // Raw data from ADC1
uint16_t ADC3_raw[CUR_RAW_ARR_LENGTH*NUMB_CHAN_PER_ADC3] = {0}; // Raw data from ADC3
int16_t ADC_sorted[CHAN_QUANTITY][CUR_RAW_ARR_LENGTH] = {0};
int16_t ADC_proceeded[CHAN_QUANTITY][CUR_PROC_ARR_LENGTH] = {0};
uint16_t* raw_ptr;
uint8_t hop_size = 0;
uint8_t Channel_decoder[9] = {0x10, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x12};
/* ADC1 ADC3
******************
* СUR2 CUR1
* CUR3 CUR6
* CUR4 CUR9
* CUR5
* CUR7
* CUR8
*/
int32_t Aver = 0;
uint8_t start_point_mark = 0; // counter for start point search (proceeding of collected data)
uint8_t filling_counter = 0; // counter for filling the arrays (proceeding of collected data)
uint8_t cycles_counter = 0; // counter of cycles of while(1) for sending data of RMS
float Res_SKZ[CHAN_QUANTITY] = {0};
uint16_t Res_SKZ2[CHAN_QUANTITY] = {0};
uint8_t Chan_ON_OFF_mask[CHAN_QUANTITY]; // !!!!!!!!!!!!!!!!!!!!!!!!
for(uint8_t i = 0; i < CHAN_QUANTITY; i++)
Chan_ON_OFF_mask[i] = 1;
while(1)
{
Prew_wake = xTaskGetTickCount();
HAL_GPIO_TogglePin(My_LED_GPIO_Port, My_LED_Pin); // LED toggle to show system is alive
// BLOCK THE PWM TASK
vTaskSuspend(PWM_task_handle);
// Switch of all the heating elements. Ones that are on - at maximum PWM
switch_heat_elems(&Flash_SETTINGS, h_el_was_ON, sizeof(h_el_was_ON)/sizeof(heat_el_t), Chan_ON_OFF_mask);
// Start measuring of current on the sensors
// ADC mode - "Scan"
for (uint8_t i = 0; i < CUR_RAW_ARR_LENGTH; i++) // Number of counts - 31 times. Once per ms
{
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC1_raw, sizeof(ADC1_raw)/sizeof(uint16_t));
HAL_ADC_Start_DMA(&hadc3, (uint32_t*)ADC3_raw, sizeof(ADC3_raw)/sizeof(uint16_t));
vTaskDelayUntil(&Prew_wake, 1);
}
// Measurement is complete
heat_el_resume_PWM();//h_el_enum);
// UNLOCK THE PWM TASK
xSemaphoreGive(Semaphore_PWM);
vTaskResume(PWM_task_handle);
/********* SORTING OF RAW ADC DATA *********/
for(Stromwand_t i = SW1; i <=SW9; i++)
{
for(uint8_t j = 0; j < 9; j++)
{
if(h_el_was_ON[j] != HEL_NO)
if(Flash_SETTINGS.Mask_matr[i][h_el_was_ON[j]] == 1) // if there is "1" in mask matrix
{
if((Channel_decoder[i] & 0x10) > 0) //
{
raw_ptr = ADC3_raw;
hop_size = 3;
}
else
{
raw_ptr = ADC1_raw;
hop_size = 6;
}
for(uint8_t a = 0; a<31; a++)
{
ADC_sorted[h_el_was_ON[j]][a] = raw_ptr[(Channel_decoder[i]&0x0F)+ a*hop_size];
}
}
}
}
/********* PROCEEDING (FILTERING) OF SORTED ADC DATA *********/
for (uint8_t i = 0; i < 9; i++) // moving on raws of sorted array
{
Aver = 0;
start_point_mark = 1;
filling_counter = 0;
if (h_el_was_ON[i] != HEL_NO)
{
for (uint8_t j = 1; j <= 15; j++)
{
if (abs(ADC_sorted[h_el_was_ON[i]][j] - ADC_sorted[h_el_was_ON[i]][j - 1]) < ADC_CURR_DIFFER)
{
start_point_mark++; // find first element, for start of sinus
start_point_mark &= 0xF;
}
else
break;
}
while (filling_counter < CUR_PROC_ARR_LENGTH)
{
ADC_proceeded[h_el_was_ON[i]][filling_counter] = ADC_sorted[h_el_was_ON[i]][start_point_mark + filling_counter]; // fill the array of proceeded data
Aver += ADC_proceeded[h_el_was_ON[i]][filling_counter];
filling_counter++;
}
Aver /= CUR_PROC_ARR_LENGTH;
uint8_t k = 0;
while (k < CUR_PROC_ARR_LENGTH)
{
ADC_proceeded[h_el_was_ON[i]][k] -= Aver;
k++;
}
}
}
/****** MEASURE THE REF ADC VOLTAGE ******/
HAL_ADCEx_InjectedStart(&hadc1);
if(HAL_ADCEx_InjectedPollForConversion(&hadc1, 2) == HAL_OK)
{
Vref_VAL = HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_1);
HAL_ADCEx_InjectedStop(&hadc1);
}
/******* CALCULATION OF THE RMS *******/
for(uint8_t i = 0; i < 9; i++)
{
if (h_el_was_ON[i] != HEL_NO)
Res_SKZ[h_el_was_ON[i]] = calc_SKZ(ADC_proceeded[h_el_was_ON[i]], CUR_PROC_ARR_LENGTH, Vref_VAL, resol_of_meas[h_el_was_ON[i]]);
else
Res_SKZ[h_el_was_ON[i]] = 0;
}
for(uint8_t i = 0; i < 9; i++)
{
Res_SKZ2[h_el_was_ON[i]] = (uint16_t)(Res_SKZ[h_el_was_ON[i]]*10);
}
cycles_counter ++;
// Transfer of an array with RMS (every 3 cycles)
if(cycles_counter >= 3)
{
cur_set_resolution(Res_SKZ, resol_of_meas);
xQueueSend(SKZ_queue, (void*)Res_SKZ, 10); // The collected data is transfered to the queue
xQueueSend(SKZ2_queue, (void*)Res_SKZ2, 10);
cycles_counter = 0;
}
vTaskDelay(Flash_SETTINGS.CS_per);
}
vTaskDelete(NULL);
}
/****************************************************/
static void Temp_sens_task (void* pvParameters)
{
/* Polling of temperature sensors. Using SPI. */
uint8_t Cont_Reg_0 = 0b10110001;
uint8_t Cont_Reg_1 = 0b00100000;
uint32_t Temperatures[CHAN_QUANTITY]; // Array where temperature will be stored
uint8_t fault_reg[CHAN_QUANTITY]; // Array for storing the content of fault registers from temp sens ICs
volatile int16_t Temper_12bit[CHAN_QUANTITY];
Set_sensors(Cont_Reg_0, Cont_Reg_1, Flash_SETTINGS.Termoc_types);
vTaskDelay(5);
while(1)
{
get_temp_value(Temperatures);
get_fault_regs(fault_reg);
for(uint8_t i = 0; i < sizeof(Temperatures)/sizeof(uint32_t); i++)
{
Temper_12bit[i] = (int16_t)((float)Temperatures[i]/4096.0)*4095/(Flash_SETTINGS.Max_temp - Flash_SETTINGS.Min_temp);
if(fault_reg[i] == 65) // Correcting of measured results. When there is no termocouple.
Temper_12bit[i] = 14045;
}
xQueueSend(Temp_queue, (void*) Temperatures, 10);
xQueueSend(Temp2_queue, (void*) Temper_12bit, 10);
xQueueSend(Fault_queue, (void*) fault_reg, 10);
vTaskDelay(Flash_SETTINGS.TS_per);
}
vTaskDelete(NULL);
}
/*************** INPUTS POLLING TASKS ***************/
static void Lin_IN_task (void* pvParameters)
{
/* Polling of linear inputs
* ADC2(channels 10, 14, 15)
*/
uint16_t Lin_In_Data[3] = {0};
volatile uint16_t Lin_In_Data_send[3] = {0};
while(1)
{
HAL_ADC_Start_DMA(&hadc2, (uint32_t*)Lin_In_Data, 3);
for(int8_t i = -1; i < 3; i++) // why start from "-1" ? I don`t know, but only now it works.
{
Lin_In_Data_send[i] = (uint16_t)((uint32_t)Lin_In_Data[i]*(uint32_t)1000/(uint32_t)4095); //
}
xQueueSend(Lin_In_queue, (void*) Lin_In_Data_send, 10);
vTaskDelay(Flash_SETTINGS.Lin_In_per);
}
vTaskDelete(NULL);
}
/****************************************************/
static void DIG_IN_task (void* pvParameters)
{
/* Polling of digital inputs*/
uint8_t Dig_In_Val = 0; // Recording of data from all inputs to one variable
while(1)
{
Dig_In_Val = Get_Dig_In_States();
xQueueSend(Dig_In_queue, (void*) &Dig_In_Val, 10);
vTaskDelay(500);
}
vTaskDelete(NULL);
}
/*************** OUTPUT SIGNALS TASKS ***************/
static void PWM_Set_task (void* pvParameters)
{
BaseType_t Sucsess_sem, Sucsess_queue;
uint16_t PWM_mtrx[CHAN_QUANTITY];
for(uint8_t i = 0; i < CHAN_QUANTITY; i++) // All PWM = 0
PWM_mtrx[i] = 0;
uint8_t Chan_ON_OFF_mask[CHAN_QUANTITY];
for(uint8_t i = 0; i < sizeof(Chan_ON_OFF_mask); i++) // !!!! should be changed to commands from main syst
Chan_ON_OFF_mask[i] = 1;
heat_elem_set_PERIOD(Flash_SETTINGS.PWM_per); //!!!!!!!1
while(1)
{
//Sucsess_queue = xQueueReceive(UART_PWM_queue, &(PWM_mtrx), 10); // Debuging line (if uncommented - comment lower line)
Sucsess_queue = xQueueReceive(PWM_Val_queue, &(PWM_mtrx), 10);
Sucsess_sem = xSemaphoreTake(Semaphore_PWM, 0);
if(Sucsess_sem == pdTRUE || Sucsess_queue == pdTRUE)
heat_elems_all_ON(PWM_mtrx, Chan_ON_OFF_mask); // All heating elements on, according to the matrix of states
}
vTaskDelete(NULL);
}
/****************************************************/
static void DIG_OUT_task(void* pvParameters)
{
/* Initialasing of digital outputs according to data received from main system */
uint8_t Dig_Out_states;
while (1)
{
xQueueReceive(Dig_Out_queue, &(Dig_Out_states), 5); // format of the received data: ХХbb bbbb
Gig_Out_On(Dig_Out_states);
vTaskDelay(500);
}
vTaskDelete(NULL);
}
/*************** FLASH MEMORY TASK ***************/
static void FLASH_operations (void* pvParameters)
{
/* Task for receiving commands from main system and rewriting flash if necessary */
Read_FLASH(&Flash_SETTINGS, sizeof(Flash_SETTINGS));
Init_RAM(&Flash_SETTINGS, Get_CAN_addr());
Write_FLASH(PARAMS_START_MEM_ADR, &Flash_SETTINGS, sizeof(Flash_SETTINGS));
while(1)
{
if (Flash_flag == 1)
{
Write_FLASH(PARAMS_START_MEM_ADR, &Flash_SETTINGS, sizeof(Flash_SETTINGS));
Flash_flag = 0;
}
vTaskDelay(500);
}
vTaskDelete(NULL);
}
/*************** UART INTERFACE TASKS ***************/
static void UART_Debug_task (void* pvParameters)
{
/* I will not comment this >:[ */
uint32_t Temperatures[CHAN_QUANTITY];
uint8_t Fault_regs[CHAN_QUANTITY];
uint16_t PWM_mtrx[CHAN_QUANTITY];
for(uint8_t i = 0; i < CHAN_QUANTITY; i++)
PWM_mtrx[i] = 0;
float SKZ[CHAN_QUANTITY] = {0};
char str_temp[10];
char str_i[20];
char str_fault[19];
char str_curr[10];
char str_vref[15];
uint8_t str_set_PWM[] = "Enter PWM Value:\n";
uint8_t str_ERROR[] = "Error in command!!!\n";
char enter[] = " \n";
while(1)
{
xQueueReceive(Temp_queue, &(Temperatures), 10);
xQueueReceive(Fault_queue, &(Fault_regs), 10);
xQueueReceive(SKZ_queue, &(SKZ), 10);
uint8_t i = PWM9;
int8_t a = 0;
sprintf(str_i, "Chan numb: %d", (i+1));
sprintf( str_temp, " %.2f", (float)Temperatures[i]/4096.0);
sprintf(str_fault, " Fault reg %d = %X", (i+1), Fault_regs[i]);
sprintf(str_vref, "Vref = %d\n", (int)Vref_VAL);
if(xUART.chan_rec_compl == 0)
{
HAL_UART_Transmit(&huart3, (uint8_t*)str_i, 13, 0xFFFF);
while(str_temp[a] != 0)
{
HAL_UART_Transmit(&huart3, (uint8_t*)(str_temp+a), 1, 0xFFFF);
a++;
}
HAL_UART_Transmit(&huart3, (uint8_t*) str_fault, 19, 0xFFFF);
HAL_UART_Transmit(&huart3, (uint8_t*) enter, sizeof(enter), 0xFFFF);
a=0;
sprintf(str_i, "Current = ");
sprintf(str_curr, "%.2f \n", (float)SKZ[i]);
HAL_UART_Transmit(&huart3, (uint8_t*)str_i, 10, 0xFFFF);
while(str_curr[a] != 0)
{
HAL_UART_Transmit(&huart3, (uint8_t*)str_curr+a, 1, 0xFFFF);
a++;
}
a = 0;
while(str_vref[a] != 0)
{
HAL_UART_Transmit(&huart3, (uint8_t*)str_vref+a, 1, 0xFFFF);
a++;
}
}
if(xUART.chan_rec_compl == 1 && xUART.PWM_rec_compl == 0)
{
if(atoi((char*)xUART.chan_numb) > 0 && atoi((char*)xUART.chan_numb) < 25)
{
HAL_UART_Transmit(&huart3, str_set_PWM, sizeof(str_set_PWM), 0xFFFF);
}
else
HAL_UART_Transmit(&huart3, str_ERROR, sizeof(str_ERROR), 0xFFFF);
}
if(xUART.chan_rec_compl == 1 && xUART.PWM_rec_compl == 1)
{
if(atoi((char*)xUART.PWM_val) >= 0 && atoi((char*)xUART.PWM_val) <= 5000) // !!!1 поменял границу
{
Flash_SETTINGS.CS_per = (uint16_t)atoi((char*)xUART.PWM_val);
xCAN.SDO_flag = 1;
//PWM_mtrx[atoi((char*)xUART.chan_numb)-1] = atoi((char*)xUART.PWM_val);
}
else
HAL_UART_Transmit(&huart3, str_ERROR, sizeof(str_ERROR), 0xFFFF);
xUART.chan_rec_compl = 0;
xUART.PWM_rec_compl = 0;
vTaskResume(PWM_task_handle);
xQueueSend(UART_PWM_queue, (void*)PWM_mtrx, 10);
}
vTaskDelay(1000);
}
vTaskDelete(NULL);
}
/*************** CAN INTERFACE TASKS ****************/
static void Curr_SEND_CAN_task (void* pvParameters)
{
HAL_StatusTypeDef Ok_or_not;
uint8_t Dev_addr = 0;
uint8_t zone = 0;
uint32_t mailbox;
Current_str Current_packet;
uint16_t Cur_val[CHAN_QUANTITY] = {0};
uint8_t txData[3] = {0};
uint8_t* ptr;
ptr = (uint8_t*)&Current_packet;
for(uint8_t i = 0; i < sizeof(Current_packet); i++)
{
ptr[i] = 0;
}
Dev_addr = Get_CAN_addr();
TX_Header_init(&txHeader_CURR ,Dev_addr, 0x180 >> 7, 3);
while(1)
{
xQueueReceive(SKZ2_queue, (void* )Cur_val, 0);
Current_packet.Zone_numb = zone;
Current_packet.Current = (uint16_t)Cur_val[zone];
memcpy(txData, &Current_packet, sizeof(Current_packet));
txData[1] = 0x0F & txData[1];
if (Flash_SETTINGS.Transm_allowed == 1)
{
Ok_or_not = HAL_CAN_AddTxMessage(&hcan2, &txHeader_CURR, txData, &mailbox);
if (Ok_or_not != HAL_OK)
{
while (1);
}
}
zone++;
if (zone > CHAN_QUANTITY-1)
{
zone = 0;
}
HAL_Delay(Flash_SETTINGS.CS_per);
}
}
/****************************************************/
static void Temp_SEND_CAN_task (void* pvParameters)
{
uint16_t Temp[CHAN_QUANTITY] = {0};
HAL_StatusTypeDef Ok_or_not;
uint8_t txData[8] = {0};
uint32_t mailbox;
uint8_t Dev_addr;
uint8_t DigIn = 0;
uint8_t zone = 0; // Number of Zone (0-7)
Temp_str Tempr_paket_str;
Dev_addr = Get_CAN_addr();
filter_init(Dev_addr);
HAL_CAN_Start(&hcan2);
HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO0_MSG_PENDING);
TX_Header_init(&txHeader_TEMP, Dev_addr, 0x280>>7, 8);
while(1)
{
xQueueReceive(Temp2_queue, (void* )Temp, 0); // Get (renew) the array with temperature
xQueueReceive(Dig_In_queue, (void*)&DigIn, 0);
Tempr_paket_str.Dig_IN = DigIn;
Tempr_paket_str.Zone_numb = zone;
Tempr_paket_str.Temperature[0] = Temp[zone];
Tempr_paket_str.Temperature[1] = Temp[zone+8];
Tempr_paket_str.Temperature[2] = Temp[zone+16];
memcpy(txData, &Tempr_paket_str, sizeof(Tempr_paket_str));
uint8_t bubble;
for(uint8_t i = 2; i < sizeof(Tempr_paket_str)-1; i+=2)
{
bubble = txData[i];
txData[i] = txData[i+1];
txData[i+1] = bubble;
}
if (Flash_SETTINGS.Transm_allowed == 1)
{
Ok_or_not = HAL_CAN_AddTxMessage(&hcan2, &txHeader_TEMP, txData, &mailbox);
if(Ok_or_not != HAL_OK)
{
while(1);
}
}
zone++;
if(zone > 7)
{
zone = 0;
}
HAL_Delay(80);
}
}
/****************************************************/
static void LinIN_SEND_CAN_task (void* pvParameters)
{
uint16_t Lin_in_data[3] = {0};
uint16_t Lin_in_packet[4] = {0};
HAL_StatusTypeDef Ok_or_not;
uint8_t Dev_addr = 0;
uint32_t mailbox;
Dev_addr = Get_CAN_addr();
filter_init(Dev_addr);
HAL_CAN_Start(&hcan2);
HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO0_MSG_PENDING);
TX_Header_init(&txHeader_LININ, Dev_addr, 0x380 >> 7, 8);
while(1)
{
xQueueReceive(Lin_In_queue, (void* )Lin_in_data, 0);
for(uint8_t i = 0; i < sizeof(Lin_in_data)/sizeof(uint16_t); i++)
{
Lin_in_packet[i] = Lin_in_data[i];
}
if (Flash_SETTINGS.Transm_allowed == 1)
{
Ok_or_not = HAL_CAN_AddTxMessage(&hcan2, &txHeader_LININ, (uint8_t*)Lin_in_packet, &mailbox);
if (Ok_or_not != HAL_OK)
{
while (1);
}
}
vTaskDelay(Flash_SETTINGS.Lin_In_per);
}
}
/**********************************************************/
static void Receive_PWM_CAN_task (void* pvParameters)
{
uint8_t Dig_out_states = 0;
uint8_t zone = 0;
uint8_t timeout_counter = 0;
uint16_t new_PWM[CHAN_QUANTITY] = {0};
uint8_t Dev_addr;
PWM_str new_PWM_str;
Dev_addr = Get_CAN_addr();
filter_init(Dev_addr);
RX_Header_init(&recHeader, Dev_addr, 0x200 >> 7, 8);
HAL_CAN_Start(&hcan2);
while(1)
{
if (xCAN.PWM_flag == 1)
{
for(uint8_t i = 2; i < 7; i+=2)
{
recData_raw[i] = 0x0F & recDataPWM[i];
}
uint8_t bubble = 0;
for (uint8_t i = 2; i < 7; i += 2)
{
bubble = recDataPWM[i];
recDataPWM[i] = recDataPWM[i + 1];
recDataPWM[i + 1] = bubble;
}
memcpy(&new_PWM_str, &recDataPWM, sizeof(recDataPWM));
Dig_out_states = new_PWM_str.Dig_outs;
xQueueSend(Dig_Out_queue, (void*)&Dig_out_states, 1);
zone = new_PWM_str.Zone_numb;
for(uint8_t i = 0; i < 3; i++)
{
new_PWM_str.New_PWM[i] = new_PWM_str.New_PWM[i]*100/4095;
}
new_PWM[zone] = new_PWM_str.New_PWM[0];
new_PWM[zone+8] = new_PWM_str.New_PWM[1];
new_PWM[zone+16] = new_PWM_str.New_PWM[2];
xQueueSend(PWM_Val_queue, (void*)new_PWM, 1);
xCAN.PWM_flag = 0;
}
else
timeout_counter++;
if(timeout_counter > 63) // 63 means that there were no new command
{
for(uint8_t i = 0; i < CHAN_QUANTITY; i++)
{
new_PWM[i] = 0;
}
xQueueSend(PWM_Val_queue, (void*)new_PWM, 1);
}
vTaskDelay(80);
}
}
/**********************************************************/
static void Receive_SDO_CAN_task (void* pvParameters)
{
SDO_str rec_SDO_packet;
SDO_str tr_SDO_packet;
uint8_t* ptr;
uint8_t bubble = 0;
uint8_t Dev_addr = 0;
volatile uint32_t Index_val = 0;
uint8_t sub;
HAL_StatusTypeDef Ok_or_not;
uint32_t mailbox;
ptr = (uint8_t*)&tr_SDO_packet;
for(uint8_t i = 0; i < sizeof(tr_SDO_packet); i++)
{
ptr[i] = 0;
}
Dev_addr = Get_CAN_addr();
TX_Header_init(&txHeader_SDO, Dev_addr, 0x580 >> 7, 8);
Dev_addr = Get_CAN_addr();
filter_init(Dev_addr);
RX_Header_init(&recHeader_SDO, Dev_addr, 0x600 >> 7, 8);
HAL_CAN_Start(&hcan2);
while(1)
{
if(xCAN.SDO_flag == 1)
{
bubble = recDataSDO[4];
recDataSDO[4] = recDataSDO[7];
recDataSDO[7] = bubble;
bubble = recDataSDO[5];
recDataSDO[5] = recDataSDO[6];
recDataSDO[6] = bubble;
sub = recDataSDO[3];
memcpy(&rec_SDO_packet, &recDataSDO, sizeof(recDataSDO));
/* Specifier processing */
if(rec_SDO_packet.Specifier & 0x80)
{
// Transmit dropping
}
else if (rec_SDO_packet.Specifier & 0x40) // Return values from memory
{
for (uint8_t i = 0; i < 3; i++)
tr_SDO_packet.Index[i] = rec_SDO_packet.Index[i];
Index_val = rec_SDO_packet.Index[1] << 8;
Index_val |= rec_SDO_packet.Index[0];
switch (Index_val)
{
case 0x7124: // Actual value shift
{
// ???
}break;
case 0x7148: // Minimal temperature (minimum measured temperature)
{
tr_SDO_packet.Specifier = calc_Spec(sizeof(Flash_SETTINGS.Min_temp));
tr_SDO_packet.Data[0] = (uint8_t) (Flash_SETTINGS.Min_temp);
tr_SDO_packet.Data[1] = (uint8_t) (Flash_SETTINGS.Min_temp >> 8);
}break;
case 0x7149: // MasbereichEnde (maximum measured temperature)
{
tr_SDO_packet.Specifier = calc_Spec(sizeof(Flash_SETTINGS.Max_temp));
tr_SDO_packet.Data[0] = (uint8_t) (Flash_SETTINGS.Max_temp);
tr_SDO_packet.Data[1] = (uint8_t) (Flash_SETTINGS.Max_temp >> 8);
}break;
case 0x7400: // Actual value
{
// ???
}break;
case 0x6410: // Actual temperature (?) value
{
// ???
}break;
case 0x6412: // Regulator value
break;
case 0x6422: // Zone on/off
break;
case 0x6425: // Control byte
break;
case 0x2002: // Terminal temperature
break;
case 0x2010: //
break;
case 0x2110: // Termocouple type return
{
tr_SDO_packet.Specifier = calc_Spec(sizeof(Flash_SETTINGS.Termoc_types[sub-1]));
tr_SDO_packet.Data[0] = Flash_SETTINGS.Termoc_types[sub-1];
}
break;
case 0x2400: // Current value
break;
case 0x2401: // Reststromistwert
break;
case 0x2403: // CurrSens poll period
{
tr_SDO_packet.Specifier = calc_Spec(sizeof((uint8_t) (Flash_SETTINGS.CS_per / 1000)));
tr_SDO_packet.Data[0] = (uint8_t) (Flash_SETTINGS.CS_per/1000);
}break;
case 0x1009: // Board version
break;
case 0x100A: // Programm version
break;
case 0x6F01: // Forbiddance of transmission
{
tr_SDO_packet.Specifier = calc_Spec(sizeof(Flash_SETTINGS.Transm_allowed));
tr_SDO_packet.Data[0] = Flash_SETTINGS.Transm_allowed;
}
break;
}
Ok_or_not = HAL_CAN_AddTxMessage(&hcan2, &txHeader_SDO, (uint8_t*) &tr_SDO_packet, &mailbox);
if (Ok_or_not != HAL_OK)
{
while (1);
}
}
else if (rec_SDO_packet.Specifier & 0x20) // Write new data
{
tr_SDO_packet.Specifier = 0x60;
for (uint8_t i = 0; i < 3; i++)
tr_SDO_packet.Index[i] = rec_SDO_packet.Index[i];
for (uint8_t i = 0; i < 4; i++)
tr_SDO_packet.Data[i] = 0;
Index_val = rec_SDO_packet.Index[1] << 8;
Index_val |= rec_SDO_packet.Index[0];
switch (Index_val)
{
case 0x7124: // Actual value shift
break;
case 0x7148: // Minimal temperature (minimum measured temperature)
{
Flash_SETTINGS.Min_temp = rec_SDO_packet.Data[2] << 8;
Flash_SETTINGS.Min_temp |= rec_SDO_packet.Data[3];
Flash_flag = 1;
}
break;
case 0x7149: // MasbereichEnde (maximum measured temperature)
{
Flash_SETTINGS.Max_temp = rec_SDO_packet.Data[2] << 8;
Flash_SETTINGS.Max_temp |= rec_SDO_packet.Data[3];
Flash_flag = 1;
}
break;
case 0x7400: // Actual value
break;
case 0x6410: // Actual temperature (?) value
break;
case 0x6412: // Regulator value
break;
case 0x6422: // Zone on/off
break;
case 0x6425: // Control byte
break;
case 0x2002: // Terminal temperature
break;
case 0x2010:
break;
case 0x2110: // Termocouple type change
{
uint8_t Cont_Reg_0 = 0b10110001;
uint8_t Cont_Reg_1 = 0b00100000;
Flash_SETTINGS.Termoc_types[sub-1] = rec_SDO_packet.Data[3];
Set_1_sensor(Cont_Reg_0, Cont_Reg_1, Flash_SETTINGS.Termoc_types[sub-1], sub-1);
Flash_flag = 1;
}
break;
case 0x2400: // Current value
break;
case 0x2401:
break;
case 0x2403: // CurrSens poll period
{
Flash_SETTINGS.CS_per = (uint16_t)(rec_SDO_packet.Data[3]*1000);
Flash_flag = 1;
}break;
case 0x1009: // Board version
break;
case 0x100A: // Programm version
break;
case 0x6F01: // Forbiddance of transmission
{
Flash_SETTINGS.Transm_allowed = rec_SDO_packet.Data[3];
Flash_flag = 1;
}
break;
}
Ok_or_not = HAL_CAN_AddTxMessage(&hcan2, &txHeader_SDO, (uint8_t*) &tr_SDO_packet, &mailbox);
if (Ok_or_not != HAL_OK)
{
while (1);
}
}
xCAN.SDO_flag = 0;
}
vTaskDelay(500);
}
}
/*************** EterCAT INTERFACE TASKS ****************/
static void ETHCAT_task(void* pvParameters)
{
unsigned char Data[1] = {0}; // Масив для SPI
volatile uint16_t CO_timer1ms = 0U; /* variable increments each millisecond */
Data[0] = 0x01; // Записуємо значення у масив, яке потрібно передати
HAL_SPI_Transmit(&hspi2, (uint8_t*) Data, 1, 10); // Передача значення по SPI
Sync_ = ASYNC; // встановлюємо асинхронний режим
CO_NMT_reset_cmd_t reset = CO_RESET_NOT;
/* increase variable each startup. Variable is stored in eeprom. */
OD_powerOnCounter++;
while (reset != CO_RESET_APP)
{
/* initialize CANopen */
CO_ReturnError_t err;
uint16_t timer1msPrevious;
// CAN NODE ID - u can change in the CO_OD.c address 0x2101 in ROM section store the value of ID
// now CAN_Node_ID = 0x30;
err = CO_init();
if (err != CO_ERROR_NO)
{
while (1)
;
/* CO_errorReport(CO->em, CO_EM_MEMORY_ALLOCATION_ERROR, CO_EMC_SOFTWARE_INTERNAL, err); */
}
reset = CO_RESET_NOT;
timer1msPrevious = CO_timer1ms;
while (reset == CO_RESET_NOT)
{
/* loop for normal program execution ******************************************/
uint16_t timer1msDiff;
timer1msDiff = CO_timer1ms - timer1msPrevious;
timer1msPrevious = CO_timer1ms;
INCREMENT_1MS(CO_timer1ms);
/*Receive data from computer*/
CO_CANinterrupt_Rx(CO->CANmodule[0]);
/* CANopen process */
reset = CO_process(CO, timer1msDiff);
// tmrTask_thread();
/* sleep for interval */
// /* Process Sync and read inputs */
// CO_process_RPDO(CO);
/* Further I/O or nonblocking application code may go here. */
/* Write outputs */
CO_process_TPDO(CO);
// /* verify timer overflow */
// if(0) {
// CO_errorReport(CO->em, CO_EM_ISR_TIMER_OVERFLOW, CO_EMC_SOFTWARE_INTERNAL, 0U);
// }
/* Nonblocking application code may go here. */
/* Process EEPROM */
}
}
/* program exit ***************************************************************/
/* stop threads */
/* delete objects from memory */
CO_delete(0/* CAN module address */);
// if ( ECAT_Init () != true) // Перевірка ініціалізаціЇ
// {
// while (1){} // Залишаємося у нескінченному циклі
// }
//
// uint8_t i = 0;
//
// while(1)
// {
// MainTask(pRPDO);
// BufferIn.Byte[0] = i++;
// int x = BufferOut.Byte[0];
//
// vTaskDelay(1000);
// }
vTaskDelete(NULL);
}
/****************************************************/
/* ADC1 ADC3
******************
* СUR2 CUR1
* CUR3 CUR6
* CUR4 CUR9
* CUR5
* CUR7
* CUR8
*/
void CO_TIMER_ISR(void)
{
// static ttimer tprof;
// saveTime(&tprof);
// CO_timer1ms++;
CO_process_RPDO(CO);
/* TODO: zpracovani RPDO dat */
/* TODO: priprava dat pro TPDO */
CO_process_TPDO(CO);
/* calculate cycle time for performance measurement */
// uint32_t t = getTime_us(&tprof);
// OD_performance[ODA_performance_timerCycleTime] = t;
// if (t > OD_performance[ODA_performance_timerCycleMaxTime])
// OD_performance[ODA_performance_timerCycleMaxTime] = t;
}
/* USER CODE END 4 */
/**
* @brief Period elapsed callback in non blocking mode
* @note This function is called when TIM6 interrupt took place, inside
* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
* a global variable "uwTick" used as application time base.
* @param htim : TIM handle
* @retval None
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
if (htim->Instance == TIM9)
{
switch (mode)
{
case 0: // Count UP
{
counter++;
if(Measure_1 == OFF)
{
if(counter > tim_9_pw_rate_chan1)
HAL_GPIO_WritePin(PWM1_GPIO_Port, PWM1_Pin, GPIO_PIN_RESET);
else
HAL_GPIO_WritePin(PWM1_GPIO_Port, PWM1_Pin, GPIO_PIN_SET);
}
if(Measure_2 == OFF)
{
if(counter > tim_9_pw_rate_chan2)
HAL_GPIO_WritePin(PWM2_GPIO_Port, PWM2_Pin, GPIO_PIN_RESET);
else
HAL_GPIO_WritePin(PWM2_GPIO_Port, PWM2_Pin, GPIO_PIN_SET);
}
if (counter == tim_9_period)
{
mode = 1;
}
} break;
case 1: // Count DOWN
{
counter--;
if(Measure_1 == OFF)
{
if(counter < tim_9_pw_rate_chan1)
HAL_GPIO_WritePin(PWM1_GPIO_Port, PWM1_Pin, GPIO_PIN_SET);
else
HAL_GPIO_WritePin(PWM1_GPIO_Port, PWM1_Pin, GPIO_PIN_RESET);
}
if(Measure_2 == OFF)
{
if(counter < tim_9_pw_rate_chan2)
HAL_GPIO_WritePin(PWM2_GPIO_Port, PWM2_Pin, GPIO_PIN_SET);
else
HAL_GPIO_WritePin(PWM2_GPIO_Port, PWM2_Pin, GPIO_PIN_RESET);
}
if (counter == 0)
{
mode = 0;
}
} break;
}
}
/* USER CODE END Callback 0 */
if (htim->Instance == TIM6) {
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
/* USER CODE END Callback 1 */
}
/**
* @brief This function is executed in case of error occurrence.
* @param file: The file name as string.
* @param line: The line in file as a number.
* @retval None
*/
void _Error_Handler(char *file, int line)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
while(1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/